package com.xyrl.third.baidu.service;

import com.alibaba.fastjson.JSONObject;
import com.xyrl.common.util.ObjectUtil;
import com.xyrl.common.util.RedisUtil;
import com.xyrl.common.util.StringUtil;
import com.xyrl.starter.lock.redis.lock.DistributedLock;
import com.xyrl.third.baidu.config.BaiduAiProperties;
import com.xyrl.third.baidu.constant.BaiduAiConstant;
import com.xyrl.third.baidu.excepton.BaiduAiException;
import com.xyrl.third.baidu.util.GsonUtils;
import com.xyrl.third.baidu.util.HttpUtil;
import com.xyrl.third.baidu.util.ImageToBase64;
import com.xyrl.third.baidu.vo.BaiduPersonVerifyVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 百度ai 身份验证
 *
 * @author zhongp
 * @version 1.0
 * @className PersonVerifyService
 * @company 星纭融链科技服务有限公司
 * @date 2020-01-07 10:09:15
 * @Description
 */
@Slf4j
public class PersonVerifyService {
    @Autowired
    private BaiduAiProperties baiduAiProperties;
    @Autowired
    private DistributedLock distributedLock;

    /**
     * base64图片 身份认证接口
     *
     * @param images    身份证图片
     * @param name      用户姓名
     * @param idCardNum 身份证号
     * @author zhongp
     * @date 2020-01-07 10:41:07
     */
    public BaiduPersonVerifyVo base64PersonVerify(String images, String name, String idCardNum) {
        return personVerify(images, BaiduAiConstant.BAIDU_PERSON_VERIFY_IMAGE_TYPE_BASE64, name, idCardNum);
    }

    /**
     * base64图片 身份认证接口
     *
     * @param in        图片流
     * @param name      用户姓名
     * @param idCardNum 身份证号
     * @author zhongp
     * @date 2020-01-07 10:41:07
     */
    public BaiduPersonVerifyVo base64PersonVerify(InputStream in, String name, String idCardNum) {
        String images = ImageToBase64.imageToBase64(in);
        return personVerify(images, BaiduAiConstant.BAIDU_PERSON_VERIFY_IMAGE_TYPE_BASE64, name, idCardNum);
    }

    /**
     * 网络图片 身份认证接口
     *
     * @param url       图片网络地址
     * @param name      用户名称
     * @param idCardNum 身份证号
     * @return
     */
    public BaiduPersonVerifyVo urlPersonVerify(String url, String name, String idCardNum) {
        return personVerify(url, BaiduAiConstant.BAIDU_PERSON_VERIFY_IMAGE_TYPE_URL, name, idCardNum);
    }

    /**
     * FACE_TOKEN人脸图片的唯一标识 身份认证接口
     *
     * @param faceToken 图片网络地址
     * @param name      用户名称
     * @param idCardNum 身份证号
     * @return
     */
    public BaiduPersonVerifyVo faceTokenPersonVerify(String faceToken, String name, String idCardNum) {
        return personVerify(faceToken, BaiduAiConstant.BAIDU_PERSON_VERIFY_IMAGE_FACE_TOKEN, name, idCardNum);
    }

    /**
     * 身份认证接口
     *
     * @param images    身份证图片
     * @param name      用户姓名
     * @param idCardNum 身份证号
     * @author zhongp
     * @date 2020-01-07 10:41:07
     */
    private BaiduPersonVerifyVo personVerify(String images, String imageType, String name, String idCardNum) {
        try {
            Map<String, Object> map = new HashMap<>();
            //图片信息(总数据大小应小于10M)，图片上传方式根据image_type来判断
            map.put("image", images);
            /**
             * 活体检测控制
             * NONE: 不进行控制
             * LOW:较低的活体要求(高通过率 低攻击拒绝率)
             * NORMAL: 一般的活体要求(平衡的攻击拒绝率, 通过率)
             * HIGH: 较高的活体要求(高攻击拒绝率 低通过率)
             * 默认NONE
             */
            map.put("liveness_control", "LOW");
            /**
             * 姓名（注：需要是UTF-8编码的中文）
             */

            map.put("name", name);
            /**
             * 身份证号码
             */
            map.put("id_card_number", idCardNum);
            /**
             * 图片类型
             * BASE64:图片的base64值，base64编码后的图片数据，编码后的图片大小不超过2M；图片尺寸不超过1920*1080
             * URL:图片的 URL地址( 可能由于网络等原因导致下载图片时间过长)；
             * FACE_TOKEN**: 人脸图片的唯一标识，调用人脸检测接口时，会为每个人脸图片赋予一个唯一的FACE_TOKEN，同一张图片多次检测得到的FACE_TOKEN是同一个。
             */
            map.put("image_type", imageType);
            /**
             * 图片质量控制
             * NONE: 不进行控制
             * LOW:较低的质量要求
             * NORMAL: 一般的质量要求
             * NORMAL: 一般的质量要求
             * HIGH: 较高的质量要求
             */
            map.put("quality_control", "NONE");
            String param = GsonUtils.toJson(map);
            String accessToken = accessToken();
            String result = HttpUtil.post(BaiduAiConstant.BAIDU_AI_PERSON_VERIFY_URL, accessToken, "application/json", param);
            log.info("百度身份认证接品返回值:{}", result);
            BaiduPersonVerifyVo vo = JSONObject.parseObject(result, BaiduPersonVerifyVo.class);
            return vo;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 获取API访问token
     * 该token有一定的有效期，需要自行管理，当失效时需重新获取.
     *
     * @return assess_token 示例： "24.460da4889caad24cccdb1fea17221975.2592000.1491995545.282335-1234567"
     */
    public String accessToken() {
        String accessToken = RedisUtil.getData(BaiduAiConstant.BAIDU_AI_ACCESS_TOKEN_CACHE_KEY);
        if (ObjectUtil.isNotEmpty(accessToken)) {
            return accessToken;
        }
        String lockKey = StringUtil.concat(BaiduAiConstant.BAIDU_AI_ACCESS_TOKEN_CACHE_KEY, ":LOCK");
        //拿到锁
        boolean isLock = distributedLock.lock(lockKey, 10);
        if (isLock) {
            //判断缓存是否己存在
            accessToken = RedisUtil.getData(BaiduAiConstant.BAIDU_AI_ACCESS_TOKEN_CACHE_KEY);
            //如果存在直接返回
            if (ObjectUtil.isNotEmpty(accessToken)) {
                return accessToken;
            }
            //取得accessToken
            return getAccessToken();
        }
        throw new BaiduAiException("取得accessToken异常");
    }

    private String getAccessToken() {
        // 获取token地址
        String authHost = StringUtil.concat(BaiduAiConstant.BAIDU_AI_AUTH_URL, "?");
        String getAccessTokenUrl = authHost
                // 1. grant_type为固定参数
                + "grant_type=client_credentials"
                // 2. 官网获取的 API Key
                + "&client_id=" + baiduAiProperties.getAccessKey()
                // 3. 官网获取的 Secret Key
                + "&client_secret=" + baiduAiProperties.getSecretKey();
        try {
            URL realUrl = new URL(getAccessTokenUrl);
            // 打开和URL之间的连接
            HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();
            connection.setRequestMethod("GET");
            connection.connect();
            // 获取所有响应头字段
            Map<String, List<String>> map = connection.getHeaderFields();
            // 遍历所有的响应头字段
            for (String key : map.keySet()) {
                System.err.println(key + "--->" + map.get(key));
            }
            // 定义 BufferedReader输入流来读取URL的响应
            BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String result = "";
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
            /**
             * 返回结果示例
             */
            System.err.println("result:" + result);
            JSONObject jsonObject = JSONObject.parseObject(result);
            String accessToken = jsonObject.getString("access_token");
            RedisUtil.setData(BaiduAiConstant.BAIDU_AI_ACCESS_TOKEN_CACHE_KEY, accessToken, baiduAiProperties.getAccessCacheTime(), TimeUnit.DAYS);
            return accessToken;
        } catch (Exception e) {
            log.error("取得百度ai access_token异常:", e);
            throw new BaiduAiException(e.getMessage());
        }
    }

}